package mh.map;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTexCoord2d;
import static org.lwjgl.opengl.GL11.glTranslated;
import static org.lwjgl.opengl.GL11.glVertex2d;

import java.util.Properties;

import mh.interfaces.Constants;
import mh.interfaces.IImage;

/**
 * This class create a new animated sprite the uses a <code>Texture</code> that contains each frame of the animation.<br>
 * The animation is a matrix of frames 3x5, each line contains a direction, each row one of the subsequential steps of
 * the movement.<br>
 * 
 * @author Gianmarco Laggia
 * 
 */
public class Tile implements IImage, Constants {
	//	/**
	//	 * The texture that stores the image for this sprite (not just one frame)
	//	 * @deprecated Use instead {@link TileSet#getTexture()}
	//	 */
	//	private Texture		texture;
	private int			id;
	private TileSet		set;
	private Properties	prop;
	/**
	 * The offset respect the main TileSet
	 */
	private int			offsetX;
	private int			offsetY;

	//	/**
	//	 * Create a new animated sprite from a specified image.
	//	 * 
	//	 * @param ref
	//	 *            A reference to the image on which this sprite should be based
	//	 * @param texX 
	//	 * @param texY 
	//	 * @deprecated Use instead <code>Tile(TileSet ts, int offsetX, int offsetY)</code>
	//	 * 
	//	 */
	//	@Deprecated
	//	public Tile(String ref, int texX, int texY) {
	//		try {
	//			this.texture = GameWindow.getTextureLoader().getTexture(ref);
	//			this.offsetX = texX;
	//			this.offsetY = texY;
	//
	//			// this.width = this.texture.getImageWidth();
	//			// this.height = this.texture.getImageHeight();
	//		} catch (IOException e) {
	//			// a tad abrupt, but our purposes if you can't find a
	//			// sprite's image you might as well give up.
	//			System.err.println("Unable to load texture: " + ref);
	//			System.exit(0);
	//		}
	//	}

	/**
	 * Creates a new Tile with a reference to the <code>TileSet</code> and a specified position in that specific set.
	 * 
	 * @param ts
	 *            The TileSet
	 * @param texX
	 *            The x position of the tile in the tileset (in tile unit)
	 * @param texY
	 *            The y position of the tile in the tileset (in tile unit)
	 */
	public Tile(TileSet ts, int texX, int texY) {
		this.set = ts;
		this.offsetX = texX;
		this.offsetY = texY;
	}

	/**
	 * Get the width of this sprite in pixels
	 * 
	 * @return The width of this sprite in pixels
	 */
	@Override
	public int getWidth() {
		return this.set.getTexture().getImageWidth();
	}

	/**
	 * Get the height of this sprite in pixels
	 * 
	 * @return The height of this sprite in pixels
	 */
	@Override
	public int getHeight() {
		return this.set.getTexture().getImageHeight();
	}

	/**
	 * Draw the sprite at the specified location
	 * 
	 * @param x
	 *            The x location where to draw this sprite
	 * @param y
	 *            The y location where to draw this sprite
	 */
	@Override
	public void draw(double x, double y) {
		// store the current model matrix
		glPushMatrix();

		// bind to the appropriate teileset for this tile
		Texture tex = this.set.getTexture();
		tex.bind();

		int tilePerRow = (int) Math.floor(tex.getImageWidth() / TILE_SIZE);
		int rowPerColumns = (int) Math.floor(tex.getImageHeight() / TILE_SIZE);

		tex.cut(tilePerRow * TILE_SIZE, rowPerColumns * TILE_SIZE);

		// translate to the right location and prepare to draw
		glTranslated(x, y + 8, 0);
		glColor3f(1, 1, 1);
		// draw a quad textured to match the sprite

		double positionXLeft = this.offsetX;
		double positionXRight = this.offsetX + 1;
		double positionYTop = this.offsetY;
		double positionYBottom = this.offsetY + 1;
		int tileSizeXLeft = 0;
		int tileSizeXRight = TILE_SIZE;
		int tileSizeYTop = 0;
		int tileSizeYBottom = TILE_SIZE;

		if (x < 0) {
			positionXLeft += 0.5;
			tileSizeXLeft = TILE_SIZE / 2;
		} else if (x >= WINDOW_WIDTH) {
			positionXRight -= 0.5;
			tileSizeXRight = TILE_SIZE / 2;
		}
		if (y < 0) {
			positionYTop += 0.5;
			tileSizeYTop = TILE_SIZE / 2;
		} else if (y >= WINDOW_HEIGHT) {
			positionYBottom -= 0.5;
			tileSizeYBottom = TILE_SIZE / 2;
		}
		glBegin(GL_QUADS);
		{

			glTexCoord2d((positionXLeft * tex.getWidth()) / tilePerRow, (positionYTop * tex.getHeight()) / rowPerColumns);
			glVertex2d(tileSizeXLeft, tileSizeYTop);
			glTexCoord2d((positionXLeft * tex.getWidth()) / tilePerRow, (positionYBottom * tex.getHeight()) / rowPerColumns);
			glVertex2d(tileSizeXLeft, tileSizeYBottom); // 384: TILE_SIZE  = 0.75:?
			glTexCoord2d((positionXRight * tex.getWidth()) / tilePerRow, (positionYBottom * tex.getHeight()) / rowPerColumns);
			glVertex2d(tileSizeXRight, tileSizeYBottom);
			glTexCoord2d((positionXRight * tex.getWidth()) / tilePerRow, (positionYTop * tex.getHeight()) / rowPerColumns);
			glVertex2d(tileSizeXRight, tileSizeYTop);
		}
		glEnd();

		// restore the model view matrix to prevent contamination
		glPopMatrix();
	}

	/**
	 * Sets the id of the tile as long as it is at least 0.
	 * 
	 * @param i
	 *            The id of the tile
	 */
	public void setId(int i) {
		if (i >= 0) {
			this.id = i;
		}
	}

	/**
	 * Returns the tile id of this tile, relative to tileset.
	 * 
	 * @return id
	 */
	public int getId() {
		return this.id;
	}

	/**
	 * Returns the property file of this Tile
	 * 
	 * @return a Property POJO
	 */
	public Properties getProperties() {
		return this.prop;
	}

	/**
	 * Sets the correct properties to this Tile
	 * 
	 * @param p
	 */
	public void setProperties(Properties p) {
		this.prop = p;
	}

	/**
	 * Tells the tile in what tileset is in
	 * 
	 * @param ts
	 */
	public void setTileSet(TileSet ts) {
		this.set = ts;
	}

	@Override
	public void setFrame(int f) {
		// TODO Auto-generated method stub

	}

	@Override
	public void frameUp() {
		// TODO Auto-generated method stub

	}

	@Override
	public void setDirection(int d) {
		//nothing to do
	}
}
